/**
 * @author 14544
 * @date 2020/3/31 14:48
 */

// 如果我们对任意网站发起 fetch 请求，那可能会出现失败情况。

// 这里的核心概念是 origin —— 域（domain）/端口（port）/协议（protocol）的组合。

// 跨源请求 —— 那些发送到其他域（即使是子域）、协议或者端口 —— 要求服务端提供特殊的头。这个政策被称为“CORS”：跨域资源共享（Cross-Origin Resource Sharing）。

{
    (async () => {
        try {
            let res = await fetch('http://www.baidu.com',{
                // mode: 'no-cors'
                // mode 选项服务类似安全守卫，用以阻止跨域请求：
                // "cors" – 默认值，允许跨域请求，可见于 Fetch：跨源请求，
                // "same-origin" – 禁止跨域请求，
                // "no-cors" – 只允许简单的跨域请求。
            });
        } catch (e) {
            throw new Error(e) //  不出意外，一定会获取失败
        }
    })()
}

// CORS 优点：因为跨源限制可以保护互联网免受恶意黑客攻击。
// 这个简单有力的规则是互联网安全的基础。例如，来自 hacker.com 页面的脚本无法访问 gmail.com 上的用户邮箱。基于这样的规则，人们感到很安全。

// 使用 <script src="http://another.com/…"> 标签。脚本元素可以有来自任何域的任何 src 值。但同样 —— 无法访问此类脚本的原始内容。
// 如果 another.com 试图公开这种访问的数据，则使用所谓的“JSONP（JSON with padding）”协议。
// 假设我们需要以这种方式从 http://another.com 站点获取数据：
{
    // 创建一个回调函数处理响应数据
    function getResponse(data){
        console.log(data)
        // document.body.removeChild(script)
    }

    const script = document.createElement('script')
    // 然后我们创建属性为 src="http://another.com/weather.json?callback=getResponse" 的 <script> 标签，请注意我们的函数名是作为它的 callback 参数。
    // 服务器动态生成一个名为 getResponse(...) 的脚本，脚本内包含我们想要接收的数据。
    script.src="http://www.baidu.com?callback=getResponse";
    document.body.appendChild(script)

    // 当远端脚本加载并执行的时候，getResponse 函数被调用，并且因为它是我们的函数，我们就有需要的数据了。
    // 缺点：1、不能发送post请求， 2、不能拦截错误

    // 这是可行的，并且不违反安全规定，因为双方网站都接受这种传递数据的方式。
    // 既然双方网站都同意这种行为，那么它肯定不是网络攻击了。现在仍然有提供这种访问的服务，因为即使是非常旧的浏览器也依然可行。
}

// 有两种跨域（cross-domain）
// 网络方法将跨源请求分为两类：“简单”请求和除“简单”请求之外其他的请求。

// 简单请求 必须满足下列条件：

// 方法：GET，POST 或 HEAD。
// 头 —— 我们仅能设置：
// Accept
// Accept-Language
// Content-Language
// Content-Type 的值为 application/x-www-form-urlencoded，multipart/form-data 或 text/plain。
// 简单请求和其他请求的本质区别在于，自古以来使用 <form> 或 <script> 标签就可以发送简单请求，而长期来浏览器都不能使用非简单请求。
//
// 所以，实际区别在于简单请求会使用 Origin 头并立即发送，而对于其他请求，浏览器会发出初步的预检请求，请求获得许可。
//
// 对于简单请求：
//
// → 浏览器发送带有源的 Origin 头。
// ← 对于没有凭据的请求（默认不发送），服务器应该设置：
// Access-Control-Allow-Origin 为 * 或与 Origin 值相同
// ← 对于具有凭据的请求，服务器应该设置：
// Access-Control-Allow-Origin 值与 Origin 相同
// Access-Control-Allow-Credentials 为 true
// 此外，如果 JavaScript 期望访问非简单响应头：
//
// Cache-Control
// Content-Language
// Content-Type
// Expires
// Last-Modified
// Pragma
// …服务器应列出 Access-Control-Expose-Headers 头中允许的那些。
//
// **对于非简单请求，会在请求之前发出初步“预检”请求：
//
// → 浏览器发送 OPTIONS 请求到相同的 url，同时具有下列头：
// Access-Control-Request-Method 请求方法。
// Access-Control-Request-Headers 非简单请求头列表
// ← 服务器应该响应状态码为 200 和响应头：
// Access-Control-Allow-Methods 具有一系列允许方法的列表，
// Access-Control-Allow-Headers 具有一系列允许头的列表，
// Access-Control-Max-Age 用指定数字来设置缓存权限的时间。
// 最后发出实际请求，应用先前的“简单”方案。
